package com.ksyun.campus.metaserver.biz.services;

import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson2.JSON;
import com.ksyun.campus.metaserver.config.MasterManager;
import com.ksyun.campus.metaserver.config.RedisSwitchManager;
import com.ksyun.campus.metaserver.entity.server.MetaServer;
import com.ksyun.campus.metaserver.mq.consumer.SyncMetaDataConsumerManager;
import com.ksyun.campus.metaserver.util.HttpRemoteUtil;
import com.ksyun.campus.metaserver.util.NetworkUtils;
import com.ksyun.campus.metaserver.util.ZooKeeperUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.util.List;

/**
 * 检查主节点心跳
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class HealthCheckServices {
    private boolean isMasterActive = true;
    @Value("${server.port}")
    private Integer serverPort;

    private final ZooKeeperUtil zooKeeperUtil;
    private final MasterManager masterManager;
    private final RegistService registService;
    private final SyncMetaDataConsumerManager syncMetaDataConsumerManager;
    private final RedisSwitchManager redisSwitchManager;

    @Scheduled(fixedRate = 2000) // 每2秒钟检查一次
    public void checkMasterHeartbeat() {
        // 是主节点直接返回
        if (masterManager.getIsMaster()) {
            return;
        }
        List<MetaServer> serverlist = zooKeeperUtil
                .getMetaServerlist(zooKeeperUtil.ZK_META_SERVER_ROOT_PATH);
        // 获取主节点
        MetaServer master = serverlist
                .stream()
                .filter(each -> Boolean.TRUE.equals(each.getIsMaster()))
                .findFirst()
                .orElse(null);
        // 获取master ip和port （不存在有可能心跳还没发过来，则写死）
        String masterIp = NetworkUtils.getLocalIp();
        Integer masterPort = serverPort == 8001 ? 8002 : 8001;
        if (ObjectUtil.isNotNull(master)) {
            masterIp = master.getIp();
            masterPort = master.getPort();
        }
        try {
            String response = HttpRemoteUtil
                    .get(masterIp + ":" + masterPort, "/meta/health", null)
                    .execute()
                    .body();
            if ("ok".equals(response)) {
                log.info("主节点健康 [port]: {}", masterPort);
                isMasterActive = true;
            } else {
                handleMasterFailure(serverPort, masterIp, masterPort);
            }
        } catch (Exception e) {
            log.error("向主节点发送心跳异常");
            handleMasterFailure(serverPort, masterIp, masterPort);
        }
    }

    /**
     * 主节点宕机 准备后事
     */
    private void handleMasterFailure(Integer serverPort, String masterIp, Integer masterPort) {
        if (isMasterActive) {
            log.error("主节点宕机 准备进行主从切换... [当前port]: {}", serverPort);
            isMasterActive = false;
            promoteToMaster(serverPort, masterIp, masterPort);
        }
    }

    private void promoteToMaster(Integer serverPort, String masterIp, Integer masterPort) {
        log.error("主节点宕机 开始执行主从切换... [当前port]: {}", serverPort);
        // 执行主从切换的逻辑
        masterManager.setIsMaster(true);
        MetaServer metaServer = MetaServer.builder()
                .isMaster(true)
                .ip(NetworkUtils.getLocalIp())
                .port(serverPort)
                .build();
        String updatedInfo = JSON.toJSONString(metaServer);
        try {
            // 新主节点主动更新zk
            registService.reportStatus();
           log.info("新主节点主动更新zk成功，MetaServer 状态已更新: {}", updatedInfo);
        } catch (Exception e) {
            log.error("新主节点主动更新zk异常 {}", updatedInfo, e);
        }

        // 关闭新主节点的消息消费者
        syncMetaDataConsumerManager.stopConsumer();

        // 切换新主节点的redis database为1好
        redisSwitchManager.switchToMaster();
    }
}
